package it.uniroma2.art.coda.casconsumer;

import it.uniroma2.art.coda.core.CODACore;
import it.uniroma2.art.coda.extension.CODAOSGiManger.Layout;
import it.uniroma2.art.coda.structures.ARTTriple;
import it.uniroma2.art.coda.structures.PreviousDecisions;
import it.uniroma2.art.coda.structures.SuggOntologyCoda;
import it.uniroma2.art.owlart.exceptions.ModelUpdateException;
import it.uniroma2.art.owlart.io.RDFFormat;
import it.uniroma2.art.owlart.model.ARTBNode;
import it.uniroma2.art.owlart.model.NodeFilters;
import it.uniroma2.art.owlart.models.OWLArtModelFactory;
import it.uniroma2.art.owlart.models.RDFModel;
import it.uniroma2.art.owlart.sesame2impl.factory.ARTModelFactorySesame2Impl;
import it.uniroma2.art.owlart.sesame2impl.models.conf.Sesame2ModelConfiguration;
import it.uniroma2.art.owlart.sesame2impl.models.conf.Sesame2NonPersistentInMemoryModelConfiguration;
import it.uniroma2.art.owlart.vocabulary.RDF;

import java.io.File;
import java.util.List;

import org.apache.uima.UimaContext;
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.jcas.JCas;
import org.apache.uima.resource.ResourceInitializationException;
import org.uimafit.component.JCasAnnotator_ImplBase;
import org.uimafit.descriptor.ConfigurationParameter;

public class CODACasConsumer extends JCasAnnotator_ImplBase {

	public static final String PARAM_BUNDLES = "bundles";
	public static final String PARAM_OSGI_CACHE = "osgiCache";
	public static final String PARAM_TEMP_DIR = "tempDir";
	public static final String PARAM_BASE_URI = "baseUri";
	public static final String PARAM_PROJECTION_RULES = "projectionRules";
	public static final String PARAM_OUTPUT_FILE = "outputFile";
	public static final String PARAM_OUTPUT_FORMAT = "outputFormat";

	@ConfigurationParameter(name = PARAM_BUNDLES, mandatory = true)
	private File bundlesDirectory;

	@ConfigurationParameter(name = PARAM_OSGI_CACHE, mandatory = true)
	private File osgiCacheDir;
	
	@ConfigurationParameter(name = PARAM_TEMP_DIR, mandatory = true)
	private File tempDir;

	@ConfigurationParameter(name = PARAM_BASE_URI, mandatory = true)
	private String baseUri;

	@ConfigurationParameter(name = PARAM_PROJECTION_RULES, mandatory = true)
	private File projectionRulesFile;
	
	@ConfigurationParameter(name = PARAM_OUTPUT_FILE, mandatory = true)
	private File outputFile;
	
	@ConfigurationParameter(name = PARAM_OUTPUT_FORMAT, mandatory = true)
	private String outputFormat = "TURTLE";

	private CODACore codaCore;
	private RDFModel rdfModel;
	private RDFModel outputModel;
	
	@Override
	public void initialize(UimaContext context)
			throws ResourceInitializationException {
		super.initialize(context);
		
		ARTModelFactorySesame2Impl factImpl = new ARTModelFactorySesame2Impl();
		OWLArtModelFactory<Sesame2ModelConfiguration> fact = OWLArtModelFactory
				.createModelFactory(factImpl);

		try {
			Sesame2NonPersistentInMemoryModelConfiguration modelConf = factImpl
					.createModelConfigurationObject(Sesame2NonPersistentInMemoryModelConfiguration.class);
			rdfModel = fact.loadRDFModel(baseUri, tempDir.getAbsolutePath(),
					modelConf);
	
			outputModel = fact.loadRDFModel(baseUri, tempDir.getAbsolutePath(),
					modelConf);

			codaCore = new CODACore();
			codaCore.initialize(osgiCacheDir, bundlesDirectory, Layout.Flat, rdfModel, new PreviousDecisions(), tempDir);			
		} catch(Exception e) {
			throw new ResourceInitializationException(e);
		}
	}
	
	@Override
	public void process(JCas aJCas) throws AnalysisEngineProcessException {
		try {			
			codaCore.setJCas(aJCas);

			while (codaCore.isAnotherAnnotationPresent()) {
				SuggOntologyCoda suggestions = codaCore.processNextAnnotation();
				List<ARTTriple> triples = suggestions.getARTTripleList();
				
				for (ARTTriple t : triples) {					
					rdfModel.addTriple(t.getSubject(), t.getPredicate(),
							t.getObject(), NodeFilters.MAINGRAPH);
				
					ARTBNode stmBNode = outputModel.createBNode();
					outputModel.addTriple(stmBNode, RDF.Res.TYPE, RDF.Res.STATEMENT, NodeFilters.MAINGRAPH);
					outputModel.addTriple(stmBNode, RDF.Res.SUBJECT, t.getSubject(), NodeFilters.MAINGRAPH);
					outputModel.addTriple(stmBNode, RDF.Res.PREDICATE, t.getPredicate(), NodeFilters.MAINGRAPH);
					outputModel.addTriple(stmBNode, RDF.Res.OBJECT, t.getObject(), NodeFilters.MAINGRAPH);
				}
			}
		} catch (Exception e) {
			throw new AnalysisEngineProcessException(e);
		}
	}
	
	@Override
	public void collectionProcessComplete() throws AnalysisEngineProcessException{
		try {
			super.collectionProcessComplete();
			outputModel.writeRDF(outputFile, RDFFormat.parseFormat(outputFormat), NodeFilters.MAINGRAPH);
			outputModel.clearRDF(NodeFilters.MAINGRAPH);
		} catch (Exception e) {
			throw new AnalysisEngineProcessException(e);
		}
	}


	@Override
	public void destroy() {
		try {
			codaCore.stopAndClose();
		} catch (ModelUpdateException e) {
			e.printStackTrace();
		}
		super.destroy();
	}
}
